package com.ejb.controller;

import com.entity.Event;
import com.ejb.controller.util.JsfUtil;
import com.ejb.controller.util.PaginationHelper;
import com.ejb.EventFacade;
import com.entity.Invitee;
import com.entity.User;

import java.io.Serializable;
import java.util.List;
import java.util.ResourceBundle;
import javax.ejb.EJB;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;

@ManagedBean(name = "eventController")
@SessionScoped
public class EventController implements Serializable
{

    private Event current;
    private Event newCurrent;
    private DataModel items = null;
    private DataModel itemsList = null;
    private DataModel searchedItems = null;
    private DataModel searchedUser = null;
    private DataModel guest = null;
    private DataModel newEventList = null;
    @EJB
    private com.ejb.EventFacade ejbFacade;
    @EJB
    private com.ejb.UserFacade userEjbFacade;
    private String searchedInput;
    private PaginationHelper pagination;
    private int selectedItemIndex;
    private int newSelectedItemIndex;
    @PersistenceContext
    private EntityManager em;

    public EventController()
    {
    }

    public DataModel getNewEventList()
    {
	List<Event> events;
	events = em.createNamedQuery("Event.findAllOrderByEventDate", Event.class).getResultList();
	if (events.size() < 12)
	{
	    newEventList = new ListDataModel(events);
	} else
	{
	    newEventList = new ListDataModel(events.subList(0, 12));
	}

	return newEventList;
    }

    public Event getNewEvent()
    {
	if (newCurrent == null)
	{
	    newCurrent = new Event();
	    newSelectedItemIndex = -1;
	}
	return newCurrent;
    }

    public String newEventPageView()
    {
	newCurrent = (Event) newEventList.getRowData();
	newSelectedItemIndex = newEventList.getRowIndex();
	return "newEventPageView";
    }

    public void setNewEventList(DataModel newEventList)
    {
	this.newEventList = newEventList;
    }

    public DataModel getGuest(Event event)
    {
	setGuest(new ListDataModel(em.createNamedQuery("Invitee.findByEventID", Invitee.class).setParameter("eventID", event).setParameter("accepted", true).getResultList()));
	//setGuest(new ListDataModel(em.createNamedQuery("Invitee.findByAccepted",Invitee.class).setParameter("accepted", true).getResultList()) );
	return guest;
    }

    public void setGuest(DataModel guest)
    {
	this.guest = guest;
    }

    public DataModel getSearchedUser()
    {
	//searchedUser = new ListDataModel(em.createNamedQuery("User.findByName",User.class).setParameter("userFirstName", "%" +"n" + "%").getResultList());
	searchedUser = new ListDataModel(em.createNamedQuery("User.findByUserLastName", User.class).setParameter("userLastName", "%yu%").getResultList());
	return searchedUser;
    }

    public void setSearchedUser(DataModel searchedUser)
    {
	this.searchedUser = searchedUser;
    }

    public Event getSelected()
    {
	if (current == null)
	{
	    current = new Event();
	    selectedItemIndex = -1;
	}
	return current;
    }

    private EventFacade getFacade()
    {
	return ejbFacade;
    }

    public PaginationHelper getPagination()
    {
	if (pagination == null)
	{
	    pagination = new PaginationHelper(10)
	    {

		@Override
		public int getItemsCount()
		{
		    FacesContext context = FacesContext.getCurrentInstance();
		    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
		    //return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}));
		    List<Event> events;
		    events = em.createNamedQuery("Event.findByUserEmail", Event.class).setParameter("userEmail", userEjbFacade.find(request.getUserPrincipal().getName())).getResultList();
		    return events.size();
		}

		@Override
		public DataModel createPageDataModel()
		{
		    FacesContext context = FacesContext.getCurrentInstance();
		    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
		    //return new ListDataModel(getFacade().findRange(new int[]{getPageFirstItem(), getPageFirstItem() + getPageSize()}));
		    List<Event> events;
		    events = em.createNamedQuery("Event.findByUserEmail", Event.class).setParameter("userEmail", userEjbFacade.find(request.getUserPrincipal().getName())).getResultList();

		    //events = em.createNamedQuery("Event.findAllOrderByEventDate",Event.class).getResultList();
		    if (getPageFirstItem() + getPageSize() > events.size())
		    {
			return new ListDataModel(events.subList(getPageFirstItem(), events.size()));
		    } else
		    {
			return new ListDataModel(events.subList(getPageFirstItem(), getPageFirstItem() + getPageSize()));
		    }
		}
	    };
	}
	return pagination;
    }

    //view single event
    public String eventPageView()
    {
	current = (Event) getItems().getRowData();
	selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
	return "eventPageView";
    }

    //edit single event

    public String eventPageEdit()
    {
	current = (Event) getItems().getRowData();
	selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
	return "eventPageEdit";
    }

    public String eventPageUpdate()
    {
	try
	{
	    getFacade().edit(current);
	    JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("EventUpdated"));
	    return "eventPageView";
	} catch (Exception e)
	{
	    JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
	    return null;
	}

    }

    //test the namedquery
    public String testQuery()
    {

	items = new ListDataModel(em.createNamedQuery("Event.findAllOrderByEventDate", Event.class).getResultList().subList(0, em.createNamedQuery("Event.findAllOrderByEventDate", Event.class).getResultList().size()));
	//items = new ListDataModel(getFacade().findAll());     
	return "home";
    }

    //searched results
    public DataModel getSearchedItems()
    {
        //searchByEventName();
	//searchByUserName();
	return searchedItems;
    }

    public void setSearchedItems(DataModel searchedItems)
    {
	this.searchedItems = searchedItems;
    }

    public String searchByUserName(){
        setSearchedItems(new ListDataModel(em.createNamedQuery("Event.findByUserEmail",Event.class).setParameter("userEmail", userEjbFacade.find("axinggu")).getResultList()));
        return "/faces/user/home";
    }
    
    public String searchByEventName(){
        setSearchedItems(new ListDataModel(em.createNamedQuery("Event.findByEventNameFuzzy",Event.class).setParameter("eventName", "%" + searchedInput + "%").setParameter("eventPublicPrivate", true).getResultList()));
        //setSearchedItems(new ListDataModel(em.createNamedQuery("Event.findAllOrderByEventDate",Event.class).getResultList()));
        return "/faces/user/home";
    }
    public String eventResultPageView() { 
        current = (Event) getSearchedItems().getRowData();
        selectedItemIndex = getSearchedItems().getRowIndex();
        return "newEventPageView";
    }
    
    public String getSearchedInput() {
        return searchedInput;
    }

    public void setSearchedInput(String searchedInput)
    {
	this.searchedInput = searchedInput;
    }

    public String prepareList()
    {
	recreateModel();
	//System.out.println(request);
	return "List";
    }

    public String prepareView()
    {
	current = (Event) getItems().getRowData();
	selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
	return "View";
    }

    public String prepareEventCreate()
    {
	current = new Event();
	selectedItemIndex = -1;
	return "/faces/user/eventCreate";
    }

    public String prepareCreate()
    {
	current = new Event();
	selectedItemIndex = -1;
	return "Create";
    }

    public String getEventList()
    {
	current = new Event();
	selectedItemIndex = -1;
	return "/faces/user/eventList";
    }

    public String eventCreate()
    {
	try
	{
	    FacesContext context = FacesContext.getCurrentInstance();
	    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
	    current.setUserEmail(userEjbFacade.find(request.getUserPrincipal().getName()));
	    getFacade().create(current);
	    JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("EventCreated"));
            items = getPagination().createPageDataModel();
	    return getEventList();
	} catch (Exception e)
	{
	    JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
	    return null;
	}
    }

    public String create()
    {
	try
	{
	    FacesContext context = FacesContext.getCurrentInstance();
	    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
	    current.setUserEmail(userEjbFacade.find(request.getUserPrincipal().getName()));
	    getFacade().create(current);
	    JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("EventCreated"));
	    return prepareCreate();
	} catch (Exception e)
	{
	    JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
	    return null;
	}
    }

    public String prepareEdit()
    {
	current = (Event) getItems().getRowData();
	selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
	return "Edit";
    }

    public String update()
    {
	try
	{
	    getFacade().edit(current);
	    JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("EventUpdated"));
	    return "View";
	} catch (Exception e)
	{
	    JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
	    return null;
	}
    }

    public String destroy()
    {
	current = (Event) getItems().getRowData();
	selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
	performDestroy();
	recreatePagination();
	recreateModel();
	return "List";
    }

    public String eventPageDelete()
    {
	current = (Event) getItems().getRowData();
	selectedItemIndex = pagination.getPageFirstItem() + getItems().getRowIndex();
	performDestroy();
	recreatePagination();
	recreateModel();
	return "eventList";
    }

    public String destroyAndView()
    {
	performDestroy();
	recreateModel();
	updateCurrentItem();
	if (selectedItemIndex >= 0)
	{
	    return "View";
	} else
	{
	    // all items were removed - go back to list
	    recreateModel();
	    return "List";
	}
    }

    private void performDestroy()
    {
	try
	{
	    getFacade().remove(current);
	    JsfUtil.addSuccessMessage(ResourceBundle.getBundle("/Bundle").getString("EventDeleted"));
	} catch (Exception e)
	{
	    JsfUtil.addErrorMessage(e, ResourceBundle.getBundle("/Bundle").getString("PersistenceErrorOccured"));
	}
    }

    private void updateCurrentItem()
    {
	int count = getFacade().count();
	if (selectedItemIndex >= count)
	{
	    // selected index cannot be bigger than number of items:
	    selectedItemIndex = count - 1;
	    // go to previous page if last page disappeared:
	    if (pagination.getPageFirstItem() >= count)
	    {
		pagination.previousPage();
	    }
	}
	if (selectedItemIndex >= 0)
	{
	    current = getFacade().findRange(new int[]
	    {
		selectedItemIndex, selectedItemIndex + 1
	    }).get(0);
	}
    }

    public DataModel getItems()
    {
	if (items == null)
	{
	    items = getPagination().createPageDataModel();
	}
	return items;
    }

    public DataModel getItemsList() {
        if (itemsList == null)
	{
	    itemsList = getPagination().createPageDataModel();
	}
        return itemsList;
    }

    public void setItemsList(DataModel itemsList) {
        this.itemsList = itemsList;
    }

    private void recreateModel()
    {
	items = null;
    }

    private void recreatePagination()
    {
	pagination = null;
    }

    public String next()
    {
	getPagination().nextPage();
	recreateModel();
	return "List";
    }

    public String nextPage()
    {
	getPagination().nextPage();
	recreateModel();
	return "eventList";
    }

    public String previouPage()
    {
	getPagination().previousPage();
	recreateModel();
	return "eventList";
    }

    public String previous()
    {
	getPagination().previousPage();
	recreateModel();
	return "List";
    }

    public SelectItem[] getItemsAvailableSelectMany()
    {
	return JsfUtil.getSelectItems(ejbFacade.findAll(), false);
    }

    public SelectItem[] getItemsAvailableSelectOne()
    {
	return JsfUtil.getSelectItems(ejbFacade.findAll(), true);
    }

//    public SelectItem[] getItemsAvailable() {
//        
//        return JsfUtil.getSelectItems(ejbFacade.find(request.getUserPrincipal().getName()), true);
//    }
    @FacesConverter(forClass = Event.class)
    public static class EventControllerConverter implements Converter
    {

	@Override
	public Object getAsObject(FacesContext facesContext, UIComponent component, String value)
	{
	    if (value == null || value.length() == 0)
	    {
		return null;
	    }
	    EventController controller = (EventController) facesContext.getApplication().getELResolver().
		    getValue(facesContext.getELContext(), null, "eventController");
	    return controller.ejbFacade.find(getKey(value));
	}

	java.lang.Integer getKey(String value)
	{
	    java.lang.Integer key;
	    key = Integer.valueOf(value);
	    return key;
	}

	String getStringKey(java.lang.Integer value)
	{
	    StringBuilder sb = new StringBuilder();
	    sb.append(value);
	    return sb.toString();
	}

	@Override
	public String getAsString(FacesContext facesContext, UIComponent component, Object object)
	{
	    if (object == null)
	    {
		return null;
	    }
	    if (object instanceof Event)
	    {
		Event o = (Event) object;
		return getStringKey(o.getEventID());
	    } else
	    {
		throw new IllegalArgumentException("object " + object + " is of type " + object.getClass().getName() + "; expected type: " + Event.class.getName());
	    }
	}

    }

}
